/**
 * description: 根据态势创建路径
 * fileName: RoutesUtils.ts
 * author: ssr
 * date: 2022-08-17 09:32:48
 * version: V1.0.0
 */
import {
  Cartesian3,
  Color,
  Entity,
  JulianDate,
  TimeInterval,
  TimeIntervalCollection,
  Math as CesiumMath,
  PolylineDashMaterialProperty,
  SampledPositionProperty,
  defined,
  CallbackProperty,
} from "cesium";
import {
  CustomViewer,
  IAnimation,
  IAnimationGroup,
} from "@@/utils/CustomCesium/CustomCesium";
import { ISideStep, IStepEntityInfo, IEntityType } from "@@/typings/observation";
import moment from "moment";
import { SideEnum } from "@@/enums/observation";

interface IEntities {
  [propName: string | number]: RouteEntity;
}

/**
 * 实体轨迹
 */
interface RouteEntity {
  id: number | string;
  name: string;
  type?: IEntityType;
  side?: SideEnum | string;
  routes: number[];
  positions: { time: JulianDate[]; data: Cartesian3[] };
}

export default class RoutesUtils {
  /**
   * 添加实体信息
   * @param entities
   * @param model
   * @param currentTime
   * @returns
   */
  private static addEntityInfo(
    entities: IEntities,
    model: IStepEntityInfo,
    currentTime: JulianDate
  ) {
    const { m_id, m_EntityName, m_Position, m_Side, m_Heading, m_EntityType } =
        model,
      cartesian3 = Cartesian3.fromDegrees(
        m_Position?.longitude || 0,
        m_Position?.latitude || 0
      );
    if (!defined(cartesian3)) return;
    /// 已存在实体信息，则继续添加旋转、位置数据
    if (entities[m_id]) {
      const entity = entities[m_id];
      /// 位置
      entity.positions.time.push(currentTime);
      entity.positions.data.push(cartesian3);
      entity.routes.push(m_Position?.longitude || 0, m_Position?.latitude || 0);
    }
    /// 添加新实体信息
    else {
      const positions: { time: JulianDate[]; data: Cartesian3[] } = {
          time: [],
          data: [],
        },
        routes: number[] = [];
      /// 位置
      positions.time.push(currentTime);
      positions.data.push(cartesian3);
      routes.push(m_Position?.longitude || 0, m_Position?.latitude || 0);
      entities[m_id] = {
        id: m_id,
        name: m_EntityName,
        side: m_Side,
        type: m_EntityType,
        // startStampTime,
        // stopStampTime,
        positions,
        routes,
      };
    }
  }

  /**
   * 创建实体
   * @param entityInfo
   */
  private static createEntity(
    entityInfo: RouteEntity,
    availability?: TimeIntervalCollection
  ) {
    const {
      id,
      name,
      side,
      type,
      //   startStampTime,
      //   stopStampTime,
      positions,
      routes,
    } = entityInfo;
    /// 动画步长为1
    let position: Cartesian3 | SampledPositionProperty =
      entityInfo.positions.data[0];
    /// 动画步长超过1
    if (positions.data.length > 1) {
      position = new SampledPositionProperty();
      /// 位置时间序列
      position.addSamples(positions.time, positions.data);
    }
    if (routes.length > 2) {
      const resourceEntity = new Entity({
        id: id + "",
        // availability,
        position,
        polyline: {
          show: !(type?.m_kind === 1 && type?.m_domain === 5),
          positions: new CallbackProperty(() => {
            return Cartesian3.fromDegreesArray(routes);
          }, false),
          width: 1,
          material: new PolylineDashMaterialProperty({
            color:
              side === 1
                ? Color.RED.withAlpha(1)
                : Color.fromCssColorString("rgba(53, 181, 255, 1)"),
          }),
        },
      });
      return resourceEntity;
    }
    return null;
  }

  /**
   * 初始创建路径
   * @param customViewer
   * @param step
   * @param visualAngle 视角
   */
  static createInitPath(
    customViewer: CustomViewer,
    step: ISideStep,
    visualAngle: string
  ) {
    const entities: IEntities = {},
      animations: IAnimation[] = [],
      /// 初始时间戳
      startStampTime = step.simul_time * 1000,
      startJulianTime = JulianDate.fromDate(moment(startStampTime).toDate()),
      endJulianTime = JulianDate.addMinutes(
        startJulianTime,
        1,
        new JulianDate()
      ),
      timeInterval = new TimeInterval({
        start: startJulianTime,
        stop: endJulianTime,
      }),
      timeIntervalCollection = new TimeIntervalCollection([timeInterval]),
      newRoutes = {};

    // 筛选实体信息
    step.obj_list && step.obj_list.forEach((model) => {
      this.addEntityInfo(entities, model, startJulianTime);
    });

    step.detect_list?.forEach((model) => {
      model.m_Side =
        visualAngle === "red"
          ? SideEnum.blue
          : visualAngle === "blue"
          ? SideEnum.red
          : model.m_Side;
      this.addEntityInfo(entities, model, startJulianTime);
    });

    // 根据实体创建动画
    for (const key in entities) {
      if (Object.prototype.hasOwnProperty.call(entities, key)) {
        const entityInfo = entities[key],
          entity = this.createEntity(entityInfo, timeIntervalCollection),
          animation =
            entity && customViewer.animationManager?.createAnimation(entity);
        // 记录轨迹点
        newRoutes[key] = entityInfo.routes;
        // 剔除无效数据
        animation?.entity.id != `undefined` &&
          animation &&
          animations.push(animation);
      }
    }
    return {
      animations,
      newRoutes,
      period: { startTime: startJulianTime, endTime: endJulianTime },
    };
  }

  /**
   * 更新路径
   * @param customViewer
   * @param step
   * @param visualAngle 视角
   */
  static updatePath(
    customViewer: CustomViewer,
    animationGroup: IAnimationGroup,
    step: ISideStep,
    visualAngle: string,
    entityRoute?: { [propName: string]: number[] },
  ) {
    const entities: IEntities = {},
      /// 初始时间戳
      startStampTime = step.simul_time * 1000,
      startJulianTime = JulianDate.fromDate(moment(startStampTime).toDate()),
      endJulianTime = JulianDate.addMinutes(
        startJulianTime,
        1,
        new JulianDate()
      ),
      timeInterval = new TimeInterval({
        start: startJulianTime,
        stop: endJulianTime,
      }),
      timeIntervalCollection = new TimeIntervalCollection([timeInterval]);

    animationGroup.removeAll();

    // 筛选实体信息
    step.obj_list && step.obj_list.forEach((model) => {
      this.addEntityInfo(entities, model, startJulianTime);
    });

    // 探测到的实体
    step.detect_list?.forEach((model) => {
      model.m_Side =
        visualAngle === "red"
          ? SideEnum.blue
          : visualAngle === "blue"
          ? SideEnum.red
          : model.m_Side;
      this.addEntityInfo(entities, model, startJulianTime);
    });

    const newRoutes = {};

    // 根据实体创建动画
    for (const key in entities) {
      if (Object.prototype.hasOwnProperty.call(entities, key)) {
        const entityInfo = entities[key],
          entity = animationGroup.datasource.entities.getById(key + "");

        if (entityRoute && Object.prototype.hasOwnProperty.call(entityRoute, key)) {
          entityRoute[entityInfo.id].push(...entityInfo.routes);
          entityInfo.routes = [...entityRoute[entityInfo.id]];
        }
        if (entity) {
          // entity.availability.addInterval(timeIntervalCollection);
          entity.polyline &&
            (entity.polyline.positions = new CallbackProperty(() => {
              return Cartesian3.fromDegreesArray(entityInfo.routes);
            }, false));
        } else {
          let newEntity = this.createEntity(entityInfo, timeIntervalCollection),
            animation =
              newEntity &&
              customViewer.animationManager?.createAnimation(newEntity);

          // 剔除无效数据
          if (animation)
            animation.id != `undefined` && animationGroup.add(animation);
        }
        newRoutes[entityInfo.id] = entityInfo.routes;
      }
    }

    return newRoutes;
  }
}
